The grid makes use of various containers, such as rows and cells, to display its data. Once these containers are no longer displayed in the viewport, they are sent to a recycling pool in order to be reused at a later time. Although everything happens automatically, it is possible to intervene in the container creation/recycling/destruction process by overriding the appropriate methods.
Here's what happens behind the scenes (we will take rows as an example):
- CreateRow : Creates and returns a new row.
- PrepareElement : Initializes the row that was created through the call to the CreateRow method. This method will only be called once per row instance.
- AttachElement : Continues the row initialization process with the item to which the row will be associated. Once the row has been fully initialized, it will be displayed on screen.
- DetachElement : Called when a row is scrolled out of view to "uninitialize" the row. This row will be made available for use by a different item (i.e., recyclable). If the row is used by a different item, the AttachElement method will be called using the path of the new item.
If a grouping, sorting, or filtering operation is made, all recyclable rows will be cleared and the initialization process from PrepareElement to DetachElement will be restarted. When a row is removed from the recycling pool, the following operations occur:
- DetachElement : Will be called for each row that is displayed in the viewport. This is the time, if required, to undo what was done in AttachElement.
- ClearElement : Will be called on all row instances—both in the viewport and in the recycling pool. This is the time, if required, to undo was was done in PrepareElement (e.g., unregister from events to prevent memory leaks). At this point, the reference to the row will be destroyed and the garbage collector will take care of releasing any allocated memory.
To resume the order of operations from beginning to end:
CreateRow -> PrepareElement -> AttachElement -> DetachElement -> ClearElement
If a row is recycled 3 times before a sorting operation is called, then the order of operations would look like:
CreateRow -> PrepareElement -> (AttachElement->DetachElement) -> (AttachElement->DetachElement) -> (AttachElement->DetachElement) -> ClearElement
Up till now, we've only referred to rows, which constitute the elements that are displayed and managed during vertical scrolling; however, the same principals apply for horizontal scrolling. Column "elements", in other words cells and column-background controls (see ColumnBackgroundControl and Cell classes), have life-cycles that are based on the same principals as the rows' with their own calls to the CreateColumnBackgroundControl/CreateCell, PrepareColumnElement, AttachColumnElement, DetachColumnElement, and ClearColumnElement methods.
Fine Print
- The AttachElement/AttachColumnElement method can be called consecutively multiple times without calling DetachElement/DetachColumnElement between each call. Every layout pass calls AttachElement/AttachColumnElement for each element. If an element is in the viewport and that remains in the viewport during the next layout pass, another call to AttachElement/AttachColumnElement —with the same parameters as the first call—will be made. This behavior was designed to allow an element to be "refreshed", if required.
- The DetachElement/DetachColumnElement method is not necessarily called as soon as an element is added to the recycling pool; it is sometimes called just prior to being attached to another item. This behavior was designed to prevent detaching an element that might be reused with exactly the same item.
- (specific to cells only) The cell-specific Create, Prepare, and Attach methods are not necessarily called at the same time as those on the containing row. For performance reasons, a row's cells are sometimes initialized after the scrolling animation completes. This behavior is what causes the "empty rows" that are shown when scrolling vertically.
- The base implementations do not need to be called when overriding the PrepareElement/PrepareColumnElement, AttachElement/AttachColumnElement, DetachElement/DetachColumnElement, and ClearElement/ClearColumnElement methods.